package io.modelcontextprotocol.sdk;

import io.modelcontextprotocol.server.McpServer;
import io.modelcontextprotocol.server.McpSyncServerExchange;

import io.modelcontextprotocol.spec.McpSchema;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

/**
 * 高级天气MCP服务器 - 演示为什么需要SSE而不是普通HTTP请求
 * <p>
 * 这个案例展示了MCP协议的核心优势： 1. 实时进度推送 2. 日志流式输出 3. 资源更新通知 4. AI交互功能
 * <p>
 * 这些功能用普通HTTP请求-响应模式是无法实现的
 */
public class AdvancedWeatherMcpServer {

    private static final Logger logger = LoggerFactory.getLogger(AdvancedWeatherMcpServer.class);

    private static final String SERVER_NAME = "Advanced Weather MCP Server";

    private static final String SERVER_VERSION = "2.0.0";

    private static final int PORT = 8080;

    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
    private final java.util.concurrent.ExecutorService asyncExecutor = Executors.newFixedThreadPool(4);
    private final java.util.concurrent.atomic.AtomicBoolean stopping = new java.util.concurrent.atomic.AtomicBoolean(false);

    private NanoHttpdSseServerTransportProvider transportProvider;

    // Jetty嵌入式服务器 + MCP内核传输层

    public static void main(String[] args) {
        AdvancedWeatherMcpServer server = new AdvancedWeatherMcpServer();
        try {
            server.start();
            logger.info("🚀 高级天气MCP服务器启动成功！");
            logger.info("📡 SSE端点: http://localhost:{}/sse", PORT);
            logger.info("📨 消息端点: http://localhost:{}/message", PORT);
            logger.info("🔧 可用工具:");
            logger.info("  - get_weather_with_progress: 带进度推送的天气查询");
            logger.info("  - get_weather_with_logs: 带日志输出的天气查询");
            logger.info("  - get_weather_with_ai: 带AI交互的天气查询");
            logger.info("  - get_weather_streaming: 流式天气数据推送");

            // 简单驻留，直到进程结束
            while (!Thread.currentThread().isInterrupted()) {
                try { Thread.sleep(1000); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); }
            }
        } catch (Exception e) {
            logger.error("❌ 服务器启动失败", e);
        } finally {
            try { server.stop(); } catch (Exception ignored) {}
        }
    }

    public void start() throws Exception {
        logger.info("🌤️ 初始化高级天气MCP服务器...");

        // 1) 构建基于 NanoHTTPD 的 MCP SSE 传输提供者
        this.transportProvider = NanoHttpdSseServerTransportProvider
                .builder()
                .port(PORT)
                .messageEndpoint("/message")
                .sseEndpoint("/sse")
                .build();

        // 2) 基于McpServer构建同步MCP服务，注册工具
        McpServer
                .sync(transportProvider)
                .serverInfo(SERVER_NAME, SERVER_VERSION)
                .toolCall(createWeatherWithProgressTool(), this::handleWeatherWithProgress)
                .toolCall(createWeatherWithLogsTool(), this::handleWeatherWithLogs)
                .toolCall(createWeatherWithAiTool(), this::handleWeatherWithAi)
                .toolCall(createWeatherStreamingTool(), this::handleWeatherStreaming)
                .build();

        // 3) NanoHTTPD 在 setSessionFactory 之后已启动，无需额外容器

    }

    public void stop() {
        if (stopping.compareAndSet(false, true)) {
            logger.info("🛑 正在停止 AdvancedWeatherMcpServer...");
            try {
                if (transportProvider != null) {
                    transportProvider.closeGracefully().block();
                }
            } catch (Exception e) {
                logger.warn("停止传输提供者时出错: {}", e.toString());
            }
            try {
                asyncExecutor.shutdownNow();
            } catch (Exception ignored) {}
            try {
                scheduler.shutdownNow();
            } catch (Exception ignored) {}
            logger.info("✅ AdvancedWeatherMcpServer 已停止");
        }
    }

    /**
     * 创建带进度推送的天气工具
     */
    private McpSchema.Tool createWeatherWithProgressTool() {
        return McpSchema.Tool.builder()
                .name("get_weather_with_progress")
                .description("获取天气信息，带实时进度推送 - 演示为什么需要SSE")
                .inputSchema(new McpSchema.JsonSchema("object",
                        Map.of("city", Map.of("type", "string", "description", "城市名称"), "country_code",
                                Map.of("type", "string", "description", "国家代码")),
                        List.of("city", "country_code"), null, null, null))
                .build();
    }

    /**
     * 创建带日志输出的天气工具
     */
    private McpSchema.Tool createWeatherWithLogsTool() {
        return McpSchema.Tool.builder()
                .name("get_weather_with_logs")
                .description("获取天气信息，带详细日志输出 - 演示实时日志推送")
                .inputSchema(new McpSchema.JsonSchema("object",
                        Map.of("city", Map.of("type", "string", "description", "城市名称"), "detailed",
                                Map.of("type", "boolean", "description", "是否获取详细信息")),
                        List.of("city"), null, null, null))
                .build();
    }

    /**
     * 创建带AI交互的天气工具
     */
    private McpSchema.Tool createWeatherWithAiTool() {
        return McpSchema.Tool.builder()
                .name("get_weather_with_ai")
                .description("获取天气信息，带AI交互功能 - 演示AI增强功能")
                .inputSchema(new McpSchema.JsonSchema("object",
                        Map.of("city", Map.of("type", "string", "description", "城市名称"), "ai_enhanced",
                                Map.of("type", "boolean", "description", "是否使用AI增强")),
                        List.of("city"), null, null, null))
                .build();
    }

    /**
     * 创建流式天气数据工具
     */
    private McpSchema.Tool createWeatherStreamingTool() {
        return McpSchema.Tool.builder()
                .name("get_weather_streaming")
                .description("流式推送天气数据 - 演示实时数据流")
                .inputSchema(new McpSchema.JsonSchema("object",
                        Map.of("city", Map.of("type", "string", "description", "城市名称"), "duration",
                                Map.of("type", "integer", "description", "推送持续时间(秒)")),
                        List.of("city"), null, null, null))
                .build();
    }

    /**
     * 处理带进度推送的天气查询 这个功能用普通HTTP请求-响应模式是无法实现的！
     */
    private McpSchema.CallToolResult handleWeatherWithProgress(McpSyncServerExchange exchange,
                                                               McpSchema.CallToolRequest request) {

        String city = (String) request.arguments().get("city");
        String countryCode = (String) request.arguments().get("country_code");
        String progressToken = request.progressToken();

        logger.info("🌤️ 开始处理带进度的天气查询: {} ({})", city, countryCode);

        // 异步处理后续步骤，避免阻塞响应
        CompletableFuture.runAsync(() -> {
            try {
                for (int count = 0; count < 60_000 && !stopping.get(); count++) {
                    exchange.progressNotification(new McpSchema.ProgressNotification(progressToken, count, 60_000d, "连接天气API...count= " + count));
                    try { Thread.sleep(5000); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); break; }
                }
            } catch (Exception e) {
                Thread.currentThread().interrupt();
                logger.error("进度推送被中断", e);
            }
        }, asyncExecutor);

        // 模拟天气数据
        String weatherData = String.format("""
                🌤️ %s (%s) 天气信息:
                🌡️ 温度: 25°C
                ☀️ 天气: 晴朗
                💨 风速: 5 km/h
                💧 湿度: 60%%
                """, city, countryCode);

        return McpSchema.CallToolResult.builder()
                .content(List.of(new McpSchema.TextContent(weatherData)))
                .isError(false)
                .build();
    }

    /**
     * 处理带日志输出的天气查询 演示实时日志推送功能
     */
    private McpSchema.CallToolResult handleWeatherWithLogs(McpSyncServerExchange exchange,
                                                           McpSchema.CallToolRequest request) {

        String city = (String) request.arguments().get("city");
        Boolean detailed = (Boolean) request.arguments().getOrDefault("detailed", false);

        logger.info("📊 开始处理带日志的天气查询: {} (详细: {})", city, detailed);

        // 异步推送日志
        CompletableFuture.runAsync(() -> {
            try {
                // 推送调试日志
                for (int count = 0; count < 60_000 && !stopping.get(); count++) {
                    exchange.loggingNotification(new McpSchema.LoggingMessageNotification(McpSchema.LoggingLevel.INFO,
                            "weather-service", "天气数据获取成功 count= " + count));
                    try { Thread.sleep(5000); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); break; }
                }

            } catch (Exception e) {
                Thread.currentThread().interrupt();
                logger.error("日志推送被中断", e);
            }
        }, asyncExecutor);

        String weatherData = String.format("""
                📊 %s 详细天气信息:
                🌡️ 当前温度: 25°C
                🌡️ 体感温度: 27°C
                ☀️ 天气状况: 晴朗
                💨 风速: 5 km/h (东北风)
                💧 湿度: 60%%
                🌡️ 气压: 1013 hPa
                🌅 日出: 06:30
                🌇 日落: 18:45
                """, city);

        return McpSchema.CallToolResult.builder()
                .content(List.of(new McpSchema.TextContent(weatherData)))
                .isError(false)
                .build();
    }

    /**
     * 处理带AI交互的天气查询 演示AI增强功能
     */
    private McpSchema.CallToolResult handleWeatherWithAi(McpSyncServerExchange exchange,
                                                         McpSchema.CallToolRequest request) {

        String city = (String) request.arguments().get("city");
        Boolean aiEnhanced = (Boolean) request.arguments().getOrDefault("ai_enhanced", false);

        logger.info("🤖 开始处理带AI的天气查询: {} (AI增强: {})", city, aiEnhanced);

        if (aiEnhanced) {
            // 异步进行AI交互
            CompletableFuture.runAsync(() -> {
                try {
                    // 推送AI处理日志
                    exchange.loggingNotification(new McpSchema.LoggingMessageNotification(McpSchema.LoggingLevel.INFO,
                            "ai-service", "启动AI天气分析..."));
                    try { Thread.sleep(1000); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); }

                } catch (Exception e) {
                    Thread.currentThread().interrupt();
                    logger.error("AI处理被中断", e);
                }
            }, asyncExecutor);
        }

        String weatherData = String.format("""
                🤖 %s AI增强天气分析:
                                
                📊 基础数据:
                🌡️ 温度: 25°C
                ☀️ 天气: 晴朗
                💨 风速: 5 km/h
                                
                🧠 AI分析:
                💡 今日天气非常适合户外活动
                🏃‍♂️ 建议进行轻度运动
                🌞 紫外线指数适中，建议涂抹防晒霜
                👕 建议穿着轻薄衣物
                                
                📈 趋势预测:
                🌡️ 明日温度预计上升2-3°C
                🌧️ 未来3天有30%%概率降雨
                """, city);

        return McpSchema.CallToolResult.builder()
                .content(List.of(new McpSchema.TextContent(weatherData)))
                .isError(false)
                .build();
    }

    /**
     * 处理流式天气数据推送 演示实时数据流功能
     */
    private McpSchema.CallToolResult handleWeatherStreaming(McpSyncServerExchange exchange,
                                                            McpSchema.CallToolRequest request) {

        String city = (String) request.arguments().get("city");
        Integer duration = (Integer) request.arguments().getOrDefault("duration", 10);
        int millis = 1000;

        logger.info("🌊 开始流式推送天气数据: {} (持续{}秒)", city, duration);

        // 异步推送流式数据
        CompletableFuture.runAsync(() -> {
            try {
                for (int count = 0; count < duration && !stopping.get(); count++) {
                    // 模拟实时天气数据更新
                    String timestamp = java.time.LocalTime.now().toString();
                    String temperature = String.format("%.1f", 20 + Math.random() * 10);
                    String humidity = String.format("%.0f", 50 + Math.random() * 20);

                    String data = String.format("[%s] %s 实时数据: 温度%s°C, 湿度%s%%, count=%d", timestamp, city, temperature, humidity, count);
                    McpSchema.LoggingMessageNotification loggingMessageNotification = new McpSchema.LoggingMessageNotification(McpSchema.LoggingLevel.INFO,
                            "weather-stream", data);
                    exchange.loggingNotification(loggingMessageNotification);

                    logger.info("sessionId= " + exchange.sessionId() + ", ===> " +data);

                    try { Thread.sleep(millis); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); break; }
                }

                exchange.loggingNotification(new McpSchema.LoggingMessageNotification(McpSchema.LoggingLevel.INFO,
                        "weather-stream", "流式数据推送完成"));

            } catch (Exception e) {
                Thread.currentThread().interrupt();
                logger.error("流式推送被中断", e);
            }
        }, asyncExecutor);

        String weatherData = String.format("""
                🌊 %s 流式天气数据已启动
                ⏱️ 推送持续时间: %d秒
                📡 数据更新频率: %d秒/次
                🔄 实时数据将通过SSE推送
                """, city, duration,millis/1000);

        return McpSchema.CallToolResult.builder()
                .content(List.of(new McpSchema.TextContent(weatherData)))
                .isError(false)
                .build();
    }

}
